"""
Zabbix API管理器
用于与Zabbix服务器进行API交互
"""
import logging
from typing import Dict, Any, Optional
from pyzabbix import ZabbixAPI, ZabbixAPIException

logger = logging.getLogger(__name__)


class ZabbixAPIManager:
    """Zabbix API管理器"""

    def __init__(self, server_config):
        """
        初始化Zabbix API管理器

        Args:
            server_config: ZabbixServer模型实例
        """
        self.server = server_config
        self.base_url = server_config.url.rstrip('/')
        self.username = server_config.username
        self.password = server_config.password
        self.api_token = server_config.api_token
        self.zapi = None

    def _connect(self) -> bool:
        """
        连接到Zabbix服务器

        Returns:
            是否连接成功
        """
        try:
            # 创建ZabbixAPI实例
            self.zapi = ZabbixAPI(self.base_url)

            # 如果有API Token，使用Token认证
            if self.api_token:
                self.zapi.session.headers.update({'Authorization': f'Bearer {self.api_token}'})
                # 测试连接
                self.zapi.apiinfo.version()
                logger.info("使用API Token连接成功")
                return True
            else:
                # 使用用户名密码登录
                self.zapi.login(self.username, self.password)
                logger.info(f"用户名密码登录成功: {self.username}")
                return True

        except ZabbixAPIException as e:
            logger.error(f"Zabbix API错误: {e}")
            return False
        except Exception as e:
            logger.error(f"连接Zabbix失败: {e}")
            return False

    def test_connection(self) -> Dict[str, Any]:
        """
        测试连接

        Returns:
            连接测试结果
        """
        try:
            # 尝试连接
            if not self._connect():
                return {
                    'success': False,
                    'error': '认证失败，请检查用户名、密码或API Token'
                }

            # 获取Zabbix版本信息
            version = self.zapi.apiinfo.version()

            # 获取基本统计信息
            hosts = self.zapi.host.get(countOutput=True)
            items = self.zapi.item.get(countOutput=True)
            triggers = self.zapi.trigger.get(countOutput=True)

            return {
                'success': True,
                'data': {
                    'version': version,
                    'total_hosts': int(hosts),
                    'total_items': int(items),
                    'total_triggers': int(triggers)
                }
            }

        except ZabbixAPIException as e:
            logger.error(f"Zabbix API错误: {e}")
            return {
                'success': False,
                'error': f'Zabbix API错误: {str(e)}'
            }
        except Exception as e:
            logger.error(f"Zabbix连接测试失败: {e}")
            return {
                'success': False,
                'error': str(e)
            }

    def get_hosts(self, **kwargs) -> Dict[str, Any]:
        """
        获取主机列表

        Returns:
            主机列表
        """
        try:
            if not self._connect():
                raise Exception("连接失败")

            params = {
                'output': 'extend',
                'selectInterfaces': 'extend',
                'selectGroups': 'extend',
                **kwargs
            }

            hosts = self.zapi.host.get(**params)
            return {
                'success': True,
                'data': hosts
            }

        except Exception as e:
            logger.error(f"获取主机列表失败: {e}")
            return {
                'success': False,
                'error': str(e)
            }

    def create_host(self, host_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        创建主机

        Args:
            host_data: 主机数据

        Returns:
            创建结果
        """
        try:
            if not self._connect():
                raise Exception("连接失败")

            result = self.zapi.host.create(host_data)
            return {
                'success': True,
                'data': result
            }

        except Exception as e:
            logger.error(f"创建主机失败: {e}")
            return {
                'success': False,
                'error': str(e)
            }

    def get_alerts(self, **kwargs) -> Dict[str, Any]:
        """
        获取告警列表

        Returns:
            告警列表
        """
        try:
            if not self._connect():
                raise Exception("连接失败")

            params = {
                'output': 'extend',
                'selectHosts': ['hostid', 'host', 'name'],
                'selectTriggers': ['triggerid', 'description', 'expression'],
                'recent': True,
                **kwargs
            }

            problems = self.zapi.problem.get(**params)

            # 为每个告警添加主机信息
            for problem in problems:
                if not problem.get('hosts') and problem.get('objectid'):
                    # 通过触发器ID获取主机信息
                    try:
                        trigger_id = problem.get('objectid')
                        triggers = self.zapi.trigger.get(
                            triggerids=[trigger_id],
                            selectHosts=['hostid', 'host', 'name'],
                            output=['triggerid']
                        )
                        if triggers and triggers[0].get('hosts'):
                            problem['hosts'] = triggers[0]['hosts']
                    except Exception as e:
                        logger.warning(f"获取触发器 {trigger_id} 的主机信息失败: {e}")

            return {
                'success': True,
                'data': problems
            }

        except Exception as e:
            logger.error(f"获取告警列表失败: {e}")
            return {
                'success': False,
                'error': str(e)
            }

    def get_host_metrics(self, host_id: str) -> Dict[str, Any]:
        """
        获取主机监控指标数据

        Args:
            host_id: Zabbix主机ID

        Returns:
            监控指标数据
        """
        try:
            if not self._connect():
                raise Exception("连接失败")

            # 获取主机所有启用的监控项
            items_result = self.zapi.item.get(
                hostids=[host_id],
                output=['itemid', 'key_', 'name', 'lastvalue', 'units'],
                filter={'status': '0'}  # 只获取启用的监控项
            )

            metrics_data = {}

            # 用于存储候选项，优先级排序
            network_in_candidates = []
            network_out_candidates = []
            disk_candidates = []

            if items_result:
                for item in items_result:
                    key = item.get('key_', '')
                    value = item.get('lastvalue', '')
                    name = item.get('name', '')

                    # 跳过空值
                    if not value or value == '':
                        continue

                    try:
                        # CPU使用率处理 - 多种模式匹配
                        if 'cpu' in key.lower() and ('util' in key.lower() or 'usage' in key.lower()):
                            if 'idle' in key.lower():
                                # CPU空闲率，需要转换为使用率
                                cpu_idle = float(value)
                                metrics_data['cpu_usage'] = round(100 - cpu_idle, 2)
                            elif 'system.cpu.util' in key and key.endswith(',idle]'):
                                cpu_idle = float(value)
                                metrics_data['cpu_usage'] = round(100 - cpu_idle, 2)
                            else:
                                # 直接的CPU使用率
                                metrics_data['cpu_usage'] = round(float(value), 2)

                        # 内存使用率处理 - 多种模式匹配
                        elif 'memory' in key.lower() or 'vm.memory' in key.lower():
                            if 'pavailable' in key.lower() or 'available' in key.lower():
                                # 可用内存百分比，需要转换为使用率
                                mem_available = float(value)
                                metrics_data['memory_usage'] = round(100 - mem_available, 2)
                            elif 'pused' in key.lower() or 'utilization' in key.lower():
                                # 直接的内存使用率
                                metrics_data['memory_usage'] = round(float(value), 2)

                        # 系统负载处理
                        elif 'system.cpu.load' in key.lower():
                            if 'load_average' not in metrics_data:
                                metrics_data['load_average'] = {}

                            if 'avg1' in key:
                                metrics_data['load_average']['1m'] = round(float(value), 2)
                            elif 'avg5' in key:
                                metrics_data['load_average']['5m'] = round(float(value), 2)
                            elif 'avg15' in key:
                                metrics_data['load_average']['15m'] = round(float(value), 2)

                        # 根分区使用率 - 优先级最高
                        elif key.startswith('vfs.fs.size[/,pused]') or key.startswith('vfs.fs.size["/",pused]'):
                            metrics_data['disk_usage'] = round(float(value), 2)

                        # 磁盘使用率候选项收集
                        elif key.startswith('vfs.dev.util['):
                            # 排除特殊设备
                            if not any(exclude in key.lower() for exclude in ['loop', 'ram', 'sr0', 'fd0', 'dm-']):
                                priority = self._get_disk_priority(key)
                                disk_candidates.append((priority, key, float(value)))

                        # 网络入流量候选项收集
                        elif key.startswith('net.if.in[') and 'dropped' not in key and 'errors' not in key:
                            # 排除回环和虚拟接口
                            if not any(exclude in key.lower() for exclude in ['lo]', 'docker', 'br-', 'veth', 'virbr']):
                                priority = self._get_network_priority(key)
                                network_in_candidates.append((priority, key, float(value)))

                        # 网络出流量候选项收集
                        elif key.startswith('net.if.out[') and 'dropped' not in key and 'errors' not in key:
                            # 排除回环和虚拟接口
                            if not any(exclude in key.lower() for exclude in ['lo]', 'docker', 'br-', 'veth', 'virbr']):
                                priority = self._get_network_priority(key)
                                network_out_candidates.append((priority, key, float(value)))

                    except Exception as e:
                        logger.warning(f"处理监控项 {key} 时出错: {e}")
                        continue

            # 选择最佳候选项
            if network_in_candidates:
                network_in_candidates.sort(key=lambda x: x[0])  # 按优先级排序
                selected_interface = network_in_candidates[0][1]
                metrics_data['network_in'] = round(network_in_candidates[0][2] / 1024, 2)  # 转换为KB/s
                logger.info(f"选择网络入流量接口: {selected_interface}")

            if network_out_candidates:
                network_out_candidates.sort(key=lambda x: x[0])
                selected_interface = network_out_candidates[0][1]
                metrics_data['network_out'] = round(network_out_candidates[0][2] / 1024, 2)  # 转换为KB/s
                logger.info(f"选择网络出流量接口: {selected_interface}")

            if disk_candidates and 'disk_usage' not in metrics_data:
                disk_candidates.sort(key=lambda x: x[0])
                selected_disk = disk_candidates[0][1]
                metrics_data['disk_usage'] = round(disk_candidates[0][2], 2)
                logger.info(f"选择磁盘设备: {selected_disk}")

            logger.info(f"主机 {host_id} 最终监控数据: {metrics_data}")



            return {
                'success': True,
                'data': metrics_data
            }

        except Exception as e:
            logger.error(f"获取主机监控指标失败: {e}")
            return {
                'success': False,
                'error': str(e)
            }

    def _get_network_priority(self, key: str) -> int:
        """
        获取网络接口优先级，数字越小优先级越高
        """
        key_lower = key.lower()

        # 最高优先级：常见的主网卡
        if any(iface in key_lower for iface in ['eth0', 'ens33', 'ens32']):
            return 1
        # 次高优先级：其他eth和ens接口
        elif any(iface in key_lower for iface in ['eth1', 'eth2', 'ens34', 'ens160', 'ens192']):
            return 2
        # 较低优先级：其他物理接口
        else:
            return 3

    def _get_disk_priority(self, key: str) -> int:
        """
        获取磁盘设备优先级，数字越小优先级越高
        """
        key_lower = key.lower()

        # 最高优先级：常见的主磁盘
        if any(disk in key_lower for disk in ['sda', 'nvme0n1', 'hda']):
            return 1
        # 次高优先级：其他常见磁盘
        elif any(disk in key_lower for disk in ['vda', 'xvda', 'sdb', 'nvme']):
            return 2
        # 较低优先级：其他磁盘
        else:
            return 3

    def _make_request(self, method: str, params: Dict[str, Any] = None) -> Any:
        """
        通用API请求方法

        Args:
            method: API方法名，如 'host.get', 'hostgroup.create'
            params: 请求参数

        Returns:
            API响应数据
        """
        try:
            if not self._connect():
                raise Exception("连接失败")

            if params is None:
                params = {}

            # 使用Zabbix API的通用请求方法
            if hasattr(self.zapi, 'do_request'):
                return self.zapi.do_request(method, params)
            else:
                # 兼容不同版本的pyzabbix
                method_parts = method.split('.')
                if len(method_parts) == 2:
                    api_object = getattr(self.zapi, method_parts[0])
                    api_method = getattr(api_object, method_parts[1])
                    return api_method(**params)
                else:
                    raise Exception(f"不支持的API方法格式: {method}")

        except Exception as e:
            logger.error(f"API请求失败 {method}: {e}")
            raise


